package com.qqbot.utils;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @Title RedissonUtil
 * @Author wenwu.cai
 * @Date 2021/11/23 18:38
 * @Description Redisson分布式锁工具类
 */
@Slf4j
@Component
public class RedissonUtil {

    public static final int DEFAULT_WAIT_TIME = 2000;
    public static final int DEFAULT_LEASE_TIME = 5000;

    @Autowired
    private RedissonClient redissonClient;

    public RLock getLock(String key) {
        return redissonClient.getLock(key);
    }

    /**
     * @param key
     * @return
     */
    public Boolean tryLock(String key) {
        return tryLock(key, DEFAULT_WAIT_TIME, DEFAULT_LEASE_TIME, TimeUnit.MILLISECONDS);
    }

    /**
     * @param key
     * @param waittime  获取锁等待时间
     * @param leaseTime 加锁后自动释放时间
     * @param unit      时间单位
     * @return
     */
    public Boolean tryLock(String key, long waittime, long leaseTime, TimeUnit unit) {
        RLock lock = getLock(key);
        try {
            return lock.tryLock(waittime, leaseTime, unit);
        } catch (InterruptedException e) {
            log.error("tryLock error", e);
        }
        return Boolean.FALSE;
    }

    public void unlock(String key) {
        try {
            RLock lock = getLock(key);
            if (lock.isLocked()) {
                lock.unlock();
            }
        } catch (Exception e) {
            log.error("key: {} unlock error: {}", key, e);
        }
    }

    /**
     * 获取目标阻塞队列
     *
     * @param queueName
     * @return
     */
    public RBlockingQueue<String> getBlockingQueue(String queueName) {
        return redissonClient.getBlockingQueue(queueName);
    }

    /**
     * 获取目标延时队列
     *
     * @param queue
     * @return
     */
    public RDelayedQueue<String> getDelayedQueue(RQueue<String> queue) {
        return redissonClient.getDelayedQueue(queue);
    }

    /**
     * 获取长整型;使用RAtomicLong实现Redis原子操作
     *
     * @param key
     * @return
     */
    public RAtomicLong getAtomicLong(String key) {
        return redissonClient.getAtomicLong(key);
    }
}
